package com.xsf.pay.common.domain;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xsf.pay.common.annotation.IsNonQueryField;
import com.xsf.pay.common.annotation.Query;
import com.xsf.pay.common.enums.QueryEnum;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 分页基础属性
 *
 * @author 呆毛一哥
 */
@Data
public class BasePageParam<T> implements Serializable {
    /**
     * 当前页数（默认为1）
     */
    @IsNonQueryField
    private long current = 1;
    /**
     * 页面行数（默认为10）
     */
    @IsNonQueryField
    private long pageSize = 10;
    /**
     * 排序字段 默认为createTime
     */
    @IsNonQueryField
    private String column = "createTime";
    /**
     * 是否正向排序 默认为false
     */
    @IsNonQueryField
    private boolean isAsc = false;

    /**
     * 获取分页对象
     *
     * @return 返回分页对象
     */
    public Page<T> getPage() {
        return new Page<>(this.current, this.pageSize);
    }

    /**
     * 将不确定类型的 Object 转换为 List
     *
     * @param obj 可能是 List、数组或其他类型
     * @return 转换后的 List
     */
    public static List<?> convertToList(Object obj) {
        try {
            if (obj instanceof Collection) {
                return (List<?>) obj;
            } else if (obj.getClass().isArray()) {
                return Arrays.asList((Object[]) obj);
            } else {
                return List.of(obj);
            }
        } catch (Exception e) {
            throw new RuntimeException("转换失败");
        }
    }

    public String camelCaseToDatabaseField(String camelCase) {
        Pattern pattern = Pattern.compile("[A-Z]");
        Matcher matcher = pattern.matcher(camelCase);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    @SneakyThrows
    public QueryWrapper<T> getQueryWrapper() {
        Class<?> clazz = this.getClass();
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Query.class)) {
                Query query = field.getAnnotation(Query.class);
                field.setAccessible(true);
                Object value = field.get(this);
                String column = camelCaseToDatabaseField(query.column());
                //未指定行则取参数名
                if (StrUtil.isBlank(column)) {
                    column = camelCaseToDatabaseField(field.getName());
                }
                if (!ObjectUtils.isEmpty(value)) {
                    for (QueryEnum queryEnum : query.value()) {
                        switch (queryEnum) {
                            case EQUAL -> queryWrapper.eq(column, field.get(this));
                            case NOT_EQUAL -> queryWrapper.ne(column, field.get(this));
                            case LIKE -> queryWrapper.like(column, field.get(this));
                            case NOT_LIKE -> queryWrapper.notLike(column, field.get(this));
                            case BETWEEN -> queryWrapper.between(column, field.get(this), field.get(this));
                            case NOT_BETWEEN -> queryWrapper.notBetween(column, field.get(this), field.get(this));
                            case IN -> queryWrapper.in(column, convertToList(field.get(this)));
                            case NOT_IN -> queryWrapper.notIn(column, field.get(this));
                            case LT -> queryWrapper.lt(column, field.get(this));
                            case GT -> queryWrapper.gt(column, field.get(this));
                            case LE -> queryWrapper.le(column, field.get(this));
                            case GE -> queryWrapper.ge(column, field.get(this));
                        }
                    }
                }
                if (Arrays.asList(query.value()).contains(QueryEnum.ORDER_BY)) {
                    queryWrapper.orderBy(true, query.orderAsc(), column);
                }
            }
        }
        return queryWrapper;
    }
}
